/*
 * Copyright (C) 2005-2013 Sourcefire, Inc. All Rights Reserved
 *
 * This file may contain proprietary rules that were created, tested and
 * certified by Sourcefire, Inc. (the "VRT Certified Rules") as well as
 * rules that were created by Sourcefire and other third parties and
 * distributed under the GNU General Public License (the "GPL Rules").  The
 * VRT Certified Rules contained in this file are the property of
 * Sourcefire, Inc. Copyright 2005 Sourcefire, Inc. All Rights Reserved.
 * The GPL Rules created by Sourcefire, Inc. are the property of
 * Sourcefire, Inc. Copyright 2002-2005 Sourcefire, Inc. All Rights
 * Reserved.  All other GPL Rules are owned and copyrighted by their
 * respective owners (please see www.snort.org/contributors for a list of
 * owners and their respective copyrights).  In order to determine what
 * rules are VRT Certified Rules or GPL Rules, please refer to the VRT
 * Certified Rules License Agreement.
 */

//#define DEBUG
#ifdef DEBUG
#define DEBUG_SO(code) code
#else
#define DEBUG_SO(code)
#endif

#include "sf_snort_plugin_api.h"
#include "sf_snort_packet.h"

#define DECODE_BUF_SIZE 24

static unsigned char decode_buf[DECODE_BUF_SIZE] = {0};

static inline uint32_t rotl32(uint32_t val, unsigned int count) {
   return (val << (count & 31)) | (val >> (32 - (count & 31)));
}

static inline uint32_t rotr32(uint32_t val, unsigned int count) {
   return (val >> (count & 31)) | (val << (32 - (count & 31)));
}

/* declare detection functions */
int rule38834eval(void *p);

/* declare rule data structures */
/* flow:established, to_server; */
static FlowFlags rule38834flow0 = 
{
   FLOW_ESTABLISHED|FLOW_TO_SERVER
};

static RuleOption rule38834option0 =
{
   OPTION_TYPE_FLOWFLAGS,
   {
      &rule38834flow0
   }
};

#ifndef CONTENT_FAST_PATTERN_ONLY
#define CONTENT_FAST_PATTERN_ONLY CONTENT_FAST_PATTERN
#endif
// content:".php", offset 0, depth 0, fast_pattern:only; 
static ContentInfo rule38834content1 = 
{
   (uint8_t *) ".php", /* pattern */
   0, /* depth */
   0, /* offset */
   CONTENT_FAST_PATTERN_ONLY|CONTENT_BUF_URI, /* flags */
   NULL, /* holder for boyer/moore PTR */
   NULL, /* more holder info - byteform */
   0, /* byteform length */
   0 /* increment length*/
};

static RuleOption rule38834option1 = 
{
   OPTION_TYPE_CONTENT,
   {
      &rule38834content1
   }
};

/* references for sid 38834 */
/* reference: url "www.virustotal.com/en/file/ee6abe4a9530b78e997d9c28394356216778eaf2d46aa3503999e7d6bfbefe90/analysis/"; */
static RuleReference rule38834ref1 = 
{
   "url", /* type */
   "www.virustotal.com/en/file/ee6abe4a9530b78e997d9c28394356216778eaf2d46aa3503999e7d6bfbefe90/analysis/" /* value */
};

static RuleReference *rule38834refs[] =
{
   &rule38834ref1,
   NULL
};

/* metadata for sid 38834 */
/* metadata:service http, policy security-ips drop, impact_flag red; */
static RuleMetaData rule38834service0 = 
{
   "service http"
};

static RuleMetaData rule38834policy1 = 
{
   "policy security-ips drop"
};

static RuleMetaData rule38834impact_flag2 = 
{
   "impact_flag red"
};

static RuleMetaData *rule38834metadata[] =
{
   &rule38834service0,
   &rule38834policy1,
   &rule38834impact_flag2,
   NULL
};

RuleOption *rule38834options[] =
{
   &rule38834option0,
   &rule38834option1,
   NULL
};

Rule rule38834 = {
   /* rule header, akin to => tcp any any -> any any */
   {
      IPPROTO_TCP, /* proto */
      "$HOME_NET", /* SRCIP     */
      "any", /* SRCPORT   */
      0, /* DIRECTION */
      "$EXTERNAL_NET", /* DSTIP     */
      "80", /* DSTPORT   */
   },
   /* metadata */
   { 
      3,  /* genid */
      38834, /* sigid */
      1, /* revision */
      "trojan-activity", /* classification */
      0,  /* hardcoded priority */
      "MALWARE-CNC Win.Trojan.Locky variant outbound connection attempt",     /* message */
      rule38834refs, /* ptr to references */
      rule38834metadata /* ptr to metadata */
   },
   rule38834options, /* ptr to rule options */
   &rule38834eval, /* uncomment to use custom detection function */
   0 /* am I initialized yet? */
};


/* detection functions */
int rule38834eval(void *p) {
   const uint8_t *cursor_normal = 0, *end_of_buffer;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   uint32_t t4,t0;
   int i;

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;
   
   // flow:established, to_server;
   if(checkFlow(p, rule38834options[0]->option_u.flowFlags) <= 0)
      return RULE_NOMATCH;
   
   // content:".php", offset 0, depth 0, fast_pattern:only;
   // if(contentMatch(p, rule38834options[1]->option_u.content, &cursor_normal) <= 0)
   //    return RULE_NOMATCH; 

   if(getBuffer(sp, CONTENT_BUF_POST, &cursor_normal, &end_of_buffer) <= 0)
      return RULE_NOMATCH;

   if(cursor_normal + DECODE_BUF_SIZE > end_of_buffer)
      return RULE_NOMATCH;

   for(i=0, t0=0xCD43EF19; i < DECODE_BUF_SIZE; i++)
   {
      t4 = cursor_normal[i] ^ (rotr32(t0, 5) & 0xFF);

      decode_buf[i] = t4 & 0xFF;

      t0 = (rotr32(i, 0x17) + 0x53702F68) ^ (rotr32(t0, 1) + rotl32(t4, (i & 0x1F)));
   }

   if(decode_buf[16] == 'i' && decode_buf[17] == 'd' && decode_buf[18] == '=')
      return RULE_MATCH;
 
   return RULE_NOMATCH;
}

/*
Rule *rules[] = {
    &rule38834,
    NULL
};
*/
